#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <cstring>
#include <unistd.h>
// #include <thread>
#include <pthread.h>



// 线程创建, 多线程共享的资源
//  volatile int gval = 100;//多线程共享全局变量

// int* data = nullptr;

// std::string fun()//多线程共享其他函数：一个重入现象
// {
//     return "我是另一个函数";
// }

// void* start_routine(void* args)
// {
//     std::string name = static_cast<const char*>(args);
//     //原则上，多线程共享堆空间
//     //堆空间, 谁申请的就属于谁
//     //往往只需要让该线程知道该堆空间的起始虚拟地址
//     //所以可以说这个堆空间是该线程所拥有的
//     data = new int(4);
//     while(true)
//     {
//         printf("我是新线程, gval: %d, &gval: %p, %s, data: %p, %d\n",
//                             gval, &gval, fun().c_str(), data, *data);
//         gval++;
//         sleep(1);
//     }
// }

// int main()
// {
//     pthread_t tid;
//     int n = pthread_create(&tid, nullptr, start_routine, (void*)"thread-1");
//     (void)n;//避免警告

//     printf("main thread create new thread tid: 0x%lx\n", tid);//tid是一个地址

//     sleep(2);//等待新线程将data空间开辟出来
//     while(true)
//     {
//         printf("我是主线程, gval: %d, &gval: %p, %s, data: %p, %d\n",
//                             gval, &gval, fun().c_str(), data, *data);
//         sleep(1);
//     }

//     return 0;
// }

// 线程退出

// void *start_routine(void *args)
// {
//     std::string name = static_cast<const char *>(args);
//     int cnt = 10;
//     while (true)
//     {
//         printf("我是新线程, name: %s\n", name.c_str());
//         cnt--;
//         if(cnt == 3)
//         {
//             printf("%s is dead\n", name.c_str());
//             int* p = nullptr;
//             *p = 0;
//         }
//         sleep(1);
//     }

//     return nullptr;//线程执行完该函数, 线程退出
// }

// int gnum = 5;

// int main()
// {
//     //多线程创建
//     std::vector<pthread_t> tids;
//     for (int i = 1; i <= gnum; ++i)
//     {
//         pthread_t tid;
//         // char buffer[64];//该buffer是所有线程共享的，所以每个线程都会对它进行修改，就导致创建的线程名不是连续的
//         char* name = new char[64];//给每个线程都申请一份空间
//         snprintf(name, 64, "thread-%d\n", i);//将线程名写入buffer
//         int n = pthread_create(&tid, nullptr, start_routine, name);
//         tids.push_back(tid);
//         (void)n; // 避免警告
//     }

//     sleep(1);
//     for (auto &tid : tids)
//     {
//         printf("main thread create new thread tid: 0x%lx\n", tid); // tid是一个地址
//     }

//     for (auto &tid : tids)
//     {
//         pthread_join(tid, nullptr);
//         printf("thread end: 0x%lu\n", tid);
//     }

//     printf("main end\n");

//     // while(true)
//     // {
//     //     printf("我是主线程");
//     //     sleep(1);
//     // }
//     // sleep(3);//主线程运行一秒就结束
//     return 0; // 进程结束
// }

// 线程退出

// void *start_routine(void *args)
// {
//     std::string name = static_cast<const char *>(args);
//     while (true)
//     {
//         printf("我是新线程, name: %s, new thread id: 0x%lx\n", name.c_str(), pthread_self());
//         sleep(1);
//         // pthread_cancel(pthread_self());//自己也可以终止自己,但不建议
//         // break;
//     }

//     // return nullptr;//方法一: 线程执行完该函数, 线程退出
//     // exit(0);//exit是用来终止进程的
//     // pthread_exit(nullptr);//方法二: 线程退出
// }

// int main()
// {
//     pthread_t tid;
//     int n = pthread_create(&tid, nullptr, start_routine, (void*)"thread-1");
//     (void)n;
//     sleep(1);
//     printf("main create new thread, main thread id: 0x%lx, new thread id: 0x%lx\n", pthread_self(), tid);

//     sleep(2);
//     pthread_cancel(tid);//方法三: 线程退出最佳实践
//     printf("cancel thread\n");

//     int m = pthread_join(tid, nullptr);
//     (void)m;

//     sleep(5);
//     printf("main end, m is %d\n", m);

// }

// 线程退出的返回值问题
// 新线程是如何将自己的返回值交给主线程的
// 主线程又是如何通过pthread_join来获得指定线程的退出信息的?
// pthread库中有对现场的封装的结构体，其中就有void* ret表示返回值的变量，
// 无论是从新线程交给主线程，还是主线程从新线程获取都是通过对库中线程结构体中的ret进行操作

// void *start_routine(void *args)
// {
//     std::string name = static_cast<const char *>(args);
//     while (true)
//     {
//         printf("我是新线程, name: %s, new thread id: 0x%lx\n", name.c_str(), pthread_self());
//         sleep(1);
//         break;
//     }

//     return (void*)10;//64位下void*占8个字节

// }

// int main()
// {
//     pthread_t tid;
//     int n = pthread_create(&tid, nullptr, start_routine, (void*)"thread-1");
//     (void)n;
//     sleep(1);
//     printf("main create new thread, main thread id: 0x%lx, new thread id: 0x%lx\n", pthread_self(), tid);

//     void* ret;
// 线程返回值 -> pthread库中线程结构体的 void* ret -> pthread_join的第二个参数
//     int m = pthread_join(tid, &ret);
//     (void)m;
//     if(m == 0)
//     {
//         printf("new thread return val: %lld\n", (long long)ret);
//     }

//     sleep(5);
//     printf("main end, m is %d\n", m);

// }

// 应用层面传参和返回值
// 传参和返回值可以是任意类型

// class Task
// {
// public:
//     Task()
//     {
//     }

//     Task(int x, int y)
//         : _x(x), _y(y), _retval(0), _code(0)
//     {
//     }

//     void Div()
//     {
//         if (_y == 0)
//         {
//             _code = 1; // 标志位, 表示结果是否正确
//             return;
//         }
//         _retval = _x / _y;
//     }

//     void Print()
//     {
//         std::cout << "retval: " << _retval << " code: " << _code << std::endl;
//     }

// private:
//     int _x;
//     int _y;
//     int _retval;
//     int _code;
// };

// void *start_routine(void *args)
// {
//     Task *t = static_cast<Task *>(args);
//     t->Div();
//     sleep(2);
//     return t;

//     // while (true)
//     // {
//     //     printf("我是新线程, name: %s, new thread id: 0x%lx\n", name.c_str(), pthread_self());
//     //     sleep(1);
//     //     break;
//     // }

//     // return (void *)10; // 64位下void*占8个字节
// }

// int main()
// {
//     pthread_t tid;
//     // 给线程传参
//     Task *t = new Task(20, 5);
//     int n = pthread_create(&tid, nullptr, start_routine, t);

//     void *ret;
//     int m = pthread_join(tid, &ret);
//     Task *retval = (Task *)ret;
//     if (m == 0)
//     {
//         printf("new thread return val: %lld\n", (long long)ret);
//     }
//     retval->Print();

//     return 0;
// }

// 线程分离

// void *start_routine(void *args)
// {
//     // pthread_detach(pthread_self()); // 自己分离自己
//     std::string name = static_cast<const char *>(args);
//     while (true)
//     {
//         printf("我是新线程, name: %s, new thread id: 0x%lx\n", name.c_str(), pthread_self());
//         sleep(1);
//         // break;
//     }

//     return (void *)10; // 64位下void*占8个字节
// }

// int main()
// {
//     pthread_t tid;
//     // 给线程传参
//     int n = pthread_create(&tid, nullptr, start_routine, (void *)"thread-1");
//     // pthread_detach(tid);//其他线程分离目标线程

//     sleep(2);
//     //PTHREAD_CANCELED: -1
//     pthread_cancel(tid);//线程被取消，返回值为-1
     
//     void *ret;
//     int m = pthread_join(tid, &ret);
//     printf("new thread return val: %lld, m: %d, error: %s\n", (long long)ret, m, strerror(m));


//     return 0;
// }
